#include "tms.hpp"

void AdminPasswdSelectionNode::init_loop()
{
    tms::PasswdI admin_pwd(tms::ADMIN_INPUT_PASSWD);

    app->mw << tms::Info(tms::ADMIN_LOGIN_INFO);
    app->mw >> admin_pwd;

    if (admin_pwd.i != ADMIN_PWD)
    {
        throw SelectionExitError(tms::PASSWD_INCORRECT);
    }

    app->l_status->set_login_status(ADMIN_L);
}

void AdminPasswdSelectionNode::exit_loop()
{
    // 重置登录状态
    app->l_status->set_login_status(NO_LOGIN);
    app->l_status->set_user_id("");
}

void CustomerSelectionNode::init_loop()
{
    tms::StringI user_id(tms::INPUT_ID);
    tms::PasswdI passwd(tms::INPUT_PASSWD);

    app->mw << tms::Info(tms::USER_LOGIN_INFO);
    app->mw >> user_id;
    app->mw << tms::Info(tms::USER_PASSWD_INPUT_INFO + user_id.i);
    app->mw >> passwd;

    try
    {
        app->be->verify_user(user_id.i, passwd.i);
    }
    catch (const std::runtime_error &e)
    {
        throw SelectionExitError(e.what());
    }

    app->l_status->set_login_status(CUSTO_L);
    app->l_status->set_user_id(user_id.i);
}

void CustomerSelectionNode::exit_loop()
{
    app->l_status->set_login_status(NO_LOGIN);
    app->l_status->set_user_id("");
}

int AShowStat::execute()
{
    std::vector<TimeTableItem> all_trains = app->be->list_all_trains();
    std::vector<UserItem> all_users = app->be->list_all_users();
    std::vector<SaleItem> all_sales = app->be->get_sales_by_user("*");

    std::stringstream info_ss;
    info_ss << "Statistics:\n";
    info_ss << "Total Trains: " << all_trains.size() << "\n";
    info_ss << "Total Users: " << all_users.size() << "\n";
    info_ss << "Total Tickets Sold: " << all_sales.size() << "\n";

    app->mw << tms::Info(info_ss.str());
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
    return 0;
}

int AModiSche::execute()
{
    tms::StringI train_id(tms::MODI_SCHE_INPUT_ID);

    app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->list_all_trains(), 20, 1));
    app->mw >> train_id;

    std::vector<TimeTableItem> target_train = app->be->query_train_by_id(train_id.i);
    if (target_train.empty())
    {
        app->mw << tms::Info(tms::SCHE_NOT_FOUND_ERR);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    std::string promote_string;
    std::string result_string;

    switch (mode)
    {
    case SPOT_ARRIVE:
        promote_string = tms::NEW_ARRIV_SPOT + train_id.i + tms::STRING_UNIT;
        break;
    case SPOT_LAUNCH:
        promote_string = tms::NEW_LAUNC_SPOT + train_id.i + tms::STRING_UNIT;
        break;
    case LAUNCH_TIME:
        promote_string = tms::NEW_LAUNC_TIME + train_id.i + tms::TIME_SPOT_UNIT;
        break;
    case DURATION:
        promote_string = tms::NEW_DURATION + train_id.i + tms::DURATION_UNIT;
        break;
    case TICKET_PRICE:
        promote_string = tms::NEW_TICKET_PRICE + train_id.i + tms::NUMBER_UNIT;
        break;
    }

    tms::StringI new_str(promote_string);
    tms::DoubleI new_double(promote_string);

    switch (mode)
    {
    case SPOT_ARRIVE:
        app->mw >> new_str;
        target_train[0].spot_arrive = new_str.i;
        result_string = app->be->modify_train(target_train[0]) ? tms::MODI_ARRIV_SPOT_SUCCESS : tms::MODI_FAIL_DB;
        break;
    case SPOT_LAUNCH:
        app->mw >> new_str;
        target_train[0].spot_launch = new_str.i;
        result_string = app->be->modify_train(target_train[0]) ? tms::MODI_LAUNC_SPOT_SUCCESS : tms::MODI_FAIL_DB;
        break;
    case LAUNCH_TIME:
        app->mw >> new_str;
        target_train[0].time_launch = new_str.i;
        result_string = app->be->modify_train(target_train[0]) ? tms::MODI_LAUNC_TIME_SUCCESS : tms::MODI_FAIL_DB;
        break;
    case DURATION:
        app->mw >> new_str;
        target_train[0].duration = new_str.i;
        result_string = app->be->modify_train(target_train[0]) ? tms::MODI_DURATION_SUCCESS : tms::MODI_FAIL_DB;
        break;
    case TICKET_PRICE:
        try
        {
            app->mw >> new_double;
        }
        catch (const std::invalid_argument &e)
        {
            result_string = e.what();
        }

        target_train[0].ticket_price = new_double.i;
        result_string = app->be->modify_train(target_train[0]) ? tms::MODI_TICKET_PRICE_SUCCESS : tms::MODI_FAIL_DB;
        break;
    }

    app->mw << tms::Info(result_string);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
    return 0;
}

int ACancSche::execute()
{
    tms::StringI train_id(tms::CANCEL_BUS_PROMOTE);
    tms::OptionI choice(tms::CONFIRM_PROMOTE);

    app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->list_all_trains(), 20, 1));
    app->mw >> train_id;

    std::vector<TimeTableItem> target_train = app->be->query_train_by_id(train_id.i);
    if (target_train.empty())
    {
        app->mw << tms::Info(tms::SCHE_NOT_FOUND_ERR);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    try
    {
        app->mw >> choice;
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    if (choice.i != OPT_YES)
    {
        app->mw << tms::Info(tms::ABORT_OPERATION);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    // 删除车次
    app->mw << tms::Info(app->be->cancel_train(train_id.i) ? train_id.i + tms::BUS_DELETE_SUCCESS : tms::MODI_FAIL_DB);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int AAddaNewb::execute()
{
    tms::StringI time_launch(tms::NEW_LAUNC_TIME + tms::TIME_SPOT_UNIT);
    tms::StringI spot_launch(tms::NEW_LAUNC_SPOT + tms::STRING_UNIT);
    tms::StringI spot_arrive(tms::NEW_ARRIV_SPOT + tms::STRING_UNIT);
    tms::StringI duration(tms::NEW_DURATION + tms::DURATION_UNIT);
    tms::DoubleI price(tms::NEW_TICKET_PRICE + tms::NUMBER_UNIT);
    tms::IntI cap(tms::NEW_CAPICITY + tms::NUMBER_UNIT);
    tms::OptionI confirm(tms::CONFIRM_PROMOTE);

    app->mw << tms::Info(tms::ADD_NEW_BUS);
    app->mw >> time_launch >> spot_launch >> spot_arrive >> duration;

    try
    {
        app->mw >> price >> cap;
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    TimeTableItem bus("0", time_launch.i, spot_launch.i, spot_arrive.i, duration.i, price.i, cap.i, 0, 0);
    std::vector<TimeTableItem> buses;
    buses.push_back(bus);

    app->mw << tms::Info(TmsDataBackend::time_table2string(buses, 20, 1));
    try
    {
        app->mw >> confirm;
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(tms::ABORT_OPERATION);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    if (confirm.i != OPT_YES)
    {
        app->mw << tms::Info(tms::ABORT_OPERATION);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    app->mw << tms::Info(app->be->add_train(bus) ? tms::ADD_NEW_BUS_SUCCESS : tms::MODI_FAIL_DB);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int ADeleSche::execute()
{
    tms::StringI bus_id(tms::ASK_DELETE_BUS_ID + tms::STRING_UNIT);
    tms::OptionI confirm(tms::CONFIRM_PROMOTE);

    app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->list_all_trains(), 20, 1));
    app->mw >> bus_id;

    try
    {
        app->mw >> confirm;
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    if (confirm.i != OPT_YES)
    {
        app->mw << tms::Info(tms::ABORT_OPERATION);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    app->mw << tms::Info(app->be->del_train(bus_id.i) ? tms::DELETE_BUS_SUCCESS : tms::MODI_FAIL_DB);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int AReadUser::execute()
{
    app->mw << tms::Info(TmsDataBackend::user2string(app->be->list_all_users(), 20));
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int AModiUser::execute()
{
    tms::StringI user_id(tms::MODI_INPUT_USER_ID);

    app->mw << tms::Info(TmsDataBackend::user2string(app->be->list_all_users(), 15));
    app->mw >> user_id;

    std::vector<UserItem> users = app->be->query_user_by_id(user_id.i);

    if (users.empty())
    {
        app->mw << tms::Info(tms::USER_NOT_FOUND_ERR);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    std::string info_string;
    std::string promote_string;
    std::string result_string;

    switch (mode)
    {
    case NAME:
        promote_string += tms::NEW_USER_NAME + tms::STRING_UNIT;
        break;
    case PASSWD:
        promote_string += tms::NEW_USER_PASSWD + tms::STRING_UNIT;
        break;

    default:
        break;
    }

    tms::StringI new_str(promote_string);
    app->mw >> new_str;

    switch (mode)
    {
    case NAME:
        users[0].name = new_str.i;
        result_string = app->be->modify_user(users[0]) ? tms::MODI_NAME_SUCCESS : tms::MODI_FAIL_DB;
        break;
    case PASSWD:
        users[0].passwd = new_str.i;
        result_string = app->be->modify_user(users[0]) ? tms::MODI_PASSWD_SUCCESS : tms::MODI_FAIL_DB;
        break;

    default:
        break;
    }

    app->mw << tms::Info(result_string);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int ADeleUser::execute()
{
    app->mw << tms::Info(TmsDataBackend::user2string(app->be->list_all_users(), 15));

    tms::StringI user_id(tms::DEL_USER_NAME + tms::STRING_UNIT);
    tms::OptionI confirm(tms::CONFIRM_PROMOTE);

    try
    {
        app->mw >> user_id >> confirm;
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    if (confirm.i != OPT_YES)
    {
        app->mw << tms::Info(tms::ABORT_OPERATION);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    // 删除用户
    app->mw << tms::Info(app->be->del_user(user_id.i) ? tms::DEL_USER_SUCCESS : tms::MODI_FAIL_DB);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int AAnasBusd::execute()
{
    const int length = 60;

    std::vector<TimeTableItem> all_trains = app->be->list_all_trains();

    std::stringstream info_ss;
    info_ss << tms::ANS_BUS_TITLE << std::endl;

    // 车次分析会自动计算车次上座率，行车行程
    for (size_t i = 0; i < all_trains.size(); i++)
    {
        double oc_rat;
        int infill, blank;
        info_ss << tms::ANS_BUS_ID << all_trains[i].time_table_id << tms::TAB << tms::ANS_BUS_OC_RAT;
        info_ss << (oc_rat = static_cast<double>(all_trains[i].ticket_sold_cnt) / all_trains[i].capacity) * 100;
        info_ss << std::endl
                << "|";
        infill = static_cast<int>(length * oc_rat);
        blank = length - infill;
        for (int j = 0; j < infill; j++)
            info_ss << "-";
        for (int j = 0; j < blank; j++)
            info_ss << " ";
        info_ss << "|" << std::endl
                << std::endl;
    }

    app->mw << tms::Info(info_ss.str());
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int AReadSche::execute()
{
    app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->list_all_trains(), 20, 1));
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int AExpoLogf::execute()
{
    tms::OptionI confirm(tms::EXPORT_LOG_PROMOTE + tms::CONFIRM_UNIT);
    tms::StringI path(tms::EXPORT_LOG_PATH + tms::STRING_UNIT);

    app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->list_all_trains(), 20, 1));

    try
    {
        app->mw >> path >> confirm;
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    if (confirm.i != OPT_YES)
    {
        app->mw << tms::Info(tms::ABORT_OPERATION);
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    app->mw << tms::Info(app->be->export_log_file(path.i) ? tms::EXPORT_LOG_SUCCESS : tms::MODI_FAIL_FILE);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int CMainPane::execute()
{
    try
    {
        UserItem user = app->be->find_user_by_id(app->l_status->get_user_id());
        std::vector<SaleItem> user_tickets = app->be->get_sales_by_user(app->l_status->get_user_id());
        std::vector<TimeTableItem> buses;
        for (size_t i = 0; i < user_tickets.size(); i++)
        {
            buses.push_back(app->be->query_train_by_id(user_tickets[i].time_id)[0]);
        }

        std::stringstream info_ss;
        info_ss << tms::USER_WELCOME << user.name << std::endl
                << std::endl;
        info_ss << tms::USER_WALLET_PREFIX << user.wallet << std::endl
                << std::endl;
        info_ss << tms::USER_ALL_TICKETS << std::endl;
        info_ss << TmsDataBackend::time_table2string(buses, 20, 1);
        info_ss << tms::USER_TICKET_PREFIX << user_tickets.size() << std::endl;

        app->mw << tms::Info(info_ss.str());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
    }
    catch (const std::runtime_error &e)
    {
        // 这个地方要是异常绝对是没登录造成的，但是正常执行绝对也不会没登录到这一步来
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    return 0;
}

int CShowTick::execute()
{
    // 有那个用户面板，我不知道做这个功能出来干什么，都能看票据，有点多余
    try
    {
        std::stringstream info_ss;
        info_ss << tms::USER_TICKET_PREFIX << std::endl;
        info_ss << TmsDataBackend::sales2string(app->be->get_sales_by_user(app->l_status->get_user_id()), 20);

        app->mw << tms::Info(info_ss.str());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
    }
    catch (const std::runtime_error &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    return 0;
}

int CSearTick::execute()
{
    tms::StringI dest(tms::USER_SEARCH_BUS_DEST + tms::STRING_UNIT);

    app->mw << tms::Info(tms::USER_SEARCH_BUS_DEST);
    app->mw >> dest;

    try
    {
        app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->query_train_by_arrive_spot(dest.i), 20, 1));
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
    }
    catch (const std::runtime_error &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    return 0;
}

int CProcTick::execute()
{
    tms::StringI bus_id(tms::PROC_TICKET_PROMOTE);
    std::string res;

    app->mw << tms::Info(TmsDataBackend::time_table2string(app->be->list_all_trains(), 20, 1));
    app->mw >> bus_id;

    try
    {
        res = app->be->purchase_ticket(app->l_status->get_user_id(), bus_id.i) ? tms::PROC_TICKET_SUCCESS : tms::MODI_FAIL_DB;
    }
    catch (const std::runtime_error &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    app->mw << tms::Info(res);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int CRefuTick::execute()
{
    tms::StringI tid(tms::REFUND_TICKET_PROMOTE);
    std::string res;

    app->mw << tms::Info(TmsDataBackend::sales2string(app->be->get_sales_by_user(app->l_status->get_user_id()), 15));
    app->mw >> tid;

    try
    {
        res = app->be->refund_ticket(app->l_status->get_user_id(), tid.i) ? tms::REFUND_TICKER_SUCCESS : tms::MODI_FAIL_DB;
    }
    catch (const std::runtime_error &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }
    app->mw << tms::Info(res);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int CModiUser::execute()
{
    std::string user_id = app->l_status->get_user_id();

    std::vector<UserItem> users = app->be->query_user_by_id(user_id);

    if (users.empty())
    {
        // 但凡是正常登录都不会执行这里
        app->mw << tms::Info(tms::USER_NOT_FOUND_ERR);
        app->mw >> tms::StringI(tms::PERSS_ANY_KEY_RETRY);
        return 0;
    }

    std::string info_string;
    std::string promote_string;
    std::string result_string;

    switch (this->mode)
    {
    case NAME:
        info_string += tms::NEW_USER_NAME + user_id;
        promote_string += tms::NEW_USER_NAME + tms::STRING_UNIT;
        break;
    case PASSWD:
        info_string += tms::NEW_USER_PASSWD + user_id;
        promote_string += tms::NEW_USER_PASSWD + tms::NEW_USER_PASSWD;
        break;

    default:
        break;
    }

    app->mw << tms::Info(info_string);
    tms::StringI new_val(promote_string);
    app->mw >> new_val;

    switch (mode)
    {
    case NAME:
        users[0].name = new_val.i;
        result_string = app->be->modify_user(users[0]) ? tms::MODI_NAME_SUCCESS : tms::MODI_FAIL_DB;
        break;
    case PASSWD:
        users[0].passwd = new_val.i;
        result_string = app->be->modify_user(users[0]) ? tms::MODI_PASSWD_SUCCESS : tms::MODI_FAIL_DB;
        break;

    default:
        break;
    }

    app->mw << tms::Info(result_string);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int CCharMony::execute()
{
    tms::DoubleI charge(tms::CHARGE_MONY + tms::DURATION_UNIT);

    if (app->be->query_user_by_id(app->l_status->get_user_id()).empty())
    {
        app->mw << tms::Info(tms::USER_NOT_FOUND_ERR);
        app->mw >> tms::StringI(tms::PERSS_ANY_KEY_RETRY);
        return 0;
    }

    try
    {
        app->mw << tms::Info(tms::CHARGE_MONY);
        app->mw >> charge;

        app->be->charge_user_wallet(app->l_status->get_user_id(), charge.i);
    }
    catch (const std::invalid_argument &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }
    catch (const std::runtime_error &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    return 0;
}

int OCustReg::execute()
{
    tms::StringI name(tms::ASK_NAME);
    tms::StringI id(tms::ASK_ID);
    tms::PasswdI psd(tms::ASK_PASSWD);

    try
    {
        app->mw << tms::Info(tms::WELCOME);
        app->mw >> name;
        app->mw << tms::Info(tms::GET_ID);
        app->mw >> id;
        app->mw << tms::Info(tms::GET_PASSWD);
        app->mw >> psd;
        app->be->register_user(UserItem(id.i, name.i, psd.i, 0.0));
    }
    catch (const std::runtime_error &e)
    {
        app->mw << tms::Info(e.what());
        app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);
        return 0;
    }

    app->mw << tms::Info(tms::THANKS);
    app->mw >> tms::StringI(tms::PRESS_ANY_KEY_CTU);

    return 0;
}

int TmsApplication::mainloop()
{
    // 管理用户登录
    AdminPasswdSelectionNode *admin_node = new AdminPasswdSelectionNode(this, tms::ADMINISTRATOR_LOGIN, this->menu);
    SelectionNode *sche_modi_select = new SelectionNode(this, tms::MODIFY_TIME_TABLE, admin_node);
    SelectionNode *user_modi_select = new SelectionNode(this, tms::MODIFY_USER_DATA, admin_node);

    admin_node->add_child(new AShowStat(this, tms::DISPLAY_STATISTICS_PAGE, admin_node));
    admin_node->add_child(new AReadSche(this, tms::READ_TIME_TABLE, admin_node));
    admin_node->add_child(sche_modi_select);
    sche_modi_select->add_child(new AModiSche(this, tms::MODIFY_SPOT_LAUNCH, sche_modi_select, SPOT_LAUNCH));
    sche_modi_select->add_child(new AModiSche(this, tms::MODIFY_SPOT_ARRIVAL, sche_modi_select, SPOT_ARRIVE));
    sche_modi_select->add_child(new AModiSche(this, tms::MODIFY_LAUNCH_TIME, sche_modi_select, LAUNCH_TIME));
    sche_modi_select->add_child(new AModiSche(this, tms::MODIFY_DURATION, sche_modi_select, DURATION));
    sche_modi_select->add_child(new AModiSche(this, tms::MODIFY_TICKET_PRICE, sche_modi_select, TICKET_PRICE));
    admin_node->add_child(new ACancSche(this, tms::CANCEL_BUS, admin_node));
    admin_node->add_child(new AReadUser(this, tms::READ_USER_DATA, admin_node));
    admin_node->add_child(user_modi_select);
    user_modi_select->add_child(new AModiUser(this, tms::MODIFY_USER_NAME, user_modi_select, NAME));
    user_modi_select->add_child(new AModiUser(this, tms::MODIFY_USER_PASSWD, user_modi_select, PASSWD));
    admin_node->add_child(new ADeleUser(this, tms::DELETE_USER, admin_node));
    admin_node->add_child(new AAnasBusd(this, tms::ANALYZE_BUS_DATA, admin_node));
    admin_node->add_child(new ADeleSche(this, tms::DELETE_BUS, admin_node));
    admin_node->add_child(new AAddaNewb(this, tms::ADD_BUS, admin_node));
    admin_node->add_child(new AExpoLogf(this, tms::EXPORT_LOG, admin_node));

    // 普通用户登录
    CustomerSelectionNode *custo_node = new CustomerSelectionNode(this, tms::CUSTOMER_LOGIN, this->menu);
    SelectionNode *cust_modi_select = new SelectionNode(this, tms::MODIFY_MY_PROFILE, custo_node);

    custo_node->add_child(new CMainPane(this, tms::PERSONAL_PANEL, custo_node));
    custo_node->add_child(new CShowTick(this, tms::ALL_BUS_ITEMS, custo_node));
    custo_node->add_child(new CSearTick(this, tms::SEARCH_BUS_TICKET, custo_node));
    custo_node->add_child(new CProcTick(this, tms::BUY_BUS_TICKET, custo_node));
    custo_node->add_child(new CRefuTick(this, tms::REFUND_BUS_TICKET, custo_node));
    custo_node->add_child(cust_modi_select);
    cust_modi_select->add_child(new CModiUser(this, tms::MODIFY_MY_USER_NAME, cust_modi_select, NAME));
    cust_modi_select->add_child(new CModiUser(this, tms::MODIFY_MY_PASSWORD, cust_modi_select, PASSWD));
    custo_node->add_child(new CCharMony(this, tms::CHARGE_MY_POCKET, custo_node));

    OCustReg *regi_user = new OCustReg(this, tms::REGISTER_NEW_USER, this->menu);

    this->menu->add_child(admin_node);
    this->menu->add_child(custo_node);
    this->menu->add_child(regi_user);

    this->menu->execute();

    return 0;
}

int main()
{
    TmsApplication *app = new TmsApplication();

    app->mainloop();
#ifdef TMS_DB_COMMIT_ENABLE
    try
    {
        app->be->commit_changes();
    }
    catch (const std::runtime_error &e)
    {
        std::cout << e.what();
    }
#endif

    return 0;
}